#region license
/*
 * Copyright (C) 2007 CchenSoft.com
 * 
 * This library is free software; you can redistribute it and/or modify it 
 * under the terms of the GNU Lesser General Public License 2.1 or later, as
 * published by the Free Software Foundation. See the included License.txt
 * or http://www.gnu.org/copyleft/lesser.html for details.
 * 
 * Author: Billy Zhang
 */
#endregion

using System.Collections;
using System;
using System.Collections.Generic;

using CchenSoft.Workflow.Query;
using CchenSoft.Workflow.Util;
using CchenSoft.Common.Utils;

namespace CchenSoft.Workflow.Spi.Memory
{

    /**
     * Simple memory implementation.
     */
    public class MemoryWorkflowStore : IWorkflowStore
    {
        //~ Static fields/initializers /////////////////////////////////////////////

        private static Hashtable entryCache = new Hashtable();
        private static Dictionary<long, IList<IStep>> currentStepsCache = new Dictionary<long, IList<IStep>>();
        private static Hashtable historyStepsCache = new Hashtable();
        private static Hashtable propertySetCache = new Hashtable();
        private static long globalEntryId = 1;
        private static long globalStepId = 1;

        //~ Methods ////////////////////////////////////////////////////////////////

        public void SetEntryState(long entryId, int state)
        {
            SimpleWorkflowEntry theEntry = (SimpleWorkflowEntry)FindEntry(entryId);
            theEntry.State = state;
        }

        public IStep CreateCurrentStep(long entryId, int stepId, String owner, DateTime startDate, DateTime? dueDate, String status, long[] previousIds)
        {
            long id = globalStepId++;
            SimpleStep step = new SimpleStep(id, entryId, stepId, 0, owner, startDate, dueDate, null, status, previousIds, null);

            IList<IStep> currentSteps = null;
            if (currentStepsCache.ContainsKey(entryId))
                currentSteps = (IList<IStep>)currentStepsCache[entryId];

            if (currentSteps == null)
            {
                currentSteps = new List<IStep>();
                currentStepsCache.Add(entryId, currentSteps);
            }

            currentSteps.Add(step);

            return step;
        }

        /**
        * Reset the MemoryWorkflowStore so it doesn't have any information.
        * Useful when testing and you don't want the MemoryWorkflowStore to
        * have old data in it.
        */
        public static void reset()
        {
            entryCache.Clear();
            currentStepsCache.Clear();
            historyStepsCache.Clear();
            propertySetCache.Clear();
        }

        public IWorkflowEntry CreateEntry(string workflowName)
        {
            long id = globalEntryId++;
            SimpleWorkflowEntry entry = new SimpleWorkflowEntry(id, workflowName, WorkflowEntryState.CREATED);
            entryCache.Add(id, entry);

            return entry;
        }

        public IList<IStep> FindCurrentSteps(long entryId)
        {
            IList<IStep> currentSteps = (IList<IStep>)currentStepsCache[entryId];

            if (currentSteps == null)
            {
                currentSteps = new List<IStep>();
                currentStepsCache.Add(entryId, currentSteps);
            }

            return currentSteps;
        }

        public IWorkflowEntry FindEntry(long entryId)
        {
            return (IWorkflowEntry)entryCache[entryId];
        }

        public IList<IStep> FindHistorySteps(long entryId)
        {
            IList<IStep> historySteps = (IList<IStep>)historyStepsCache[entryId];

            if (historySteps == null)
            {
                historySteps = new List<IStep>();
                historyStepsCache.Add(entryId, historySteps);
            }

            return historySteps;
        }

        public void Init(IDictionary props)
        {
        }

        public IStep MarkFinished(IStep step, int actionId, DateTime? finishDate, string status, string caller)
        {
            IList currentSteps = (IList)currentStepsCache[step.EntryId];

            for (IEnumerator iterator = currentSteps.GetEnumerator(); iterator.MoveNext(); )
            {
                SimpleStep theStep = (SimpleStep)iterator.Current;

                if (theStep.Id == step.Id)
                {
                    theStep.Status = status;
                    theStep.ActionId = actionId;
                    theStep.FinishDate = finishDate;
                    theStep.Caller = caller;

                    return theStep;
                }
            }

            return null;
        }

        public void MoveToHistory(IStep step)
        {
            IList currentSteps = (IList)currentStepsCache[step.EntryId];

            IList historySteps = (IList)historyStepsCache[step.EntryId];

            if (historySteps == null)
            {
                historySteps = new ArrayList();
                historyStepsCache.Add(step.EntryId, historySteps);
            }

            SimpleStep simpleStep = (SimpleStep)step;
            IStep currentStep = null;
            for (IEnumerator iterator = currentSteps.GetEnumerator(); iterator.MoveNext(); )
            {
                currentStep = (IStep)iterator.Current;

                if (simpleStep.Id == currentStep.Id)
                {
                    //iterator.Remove();
                    historySteps.Insert(0, simpleStep);

                    break;
                }
            }

            currentSteps.Remove(currentStep);
        }

        public IList<long> Query(WorkflowQuery q)
        {
            List<long> results = new List<long>();

            for (IDictionaryEnumerator iterator = entryCache.GetEnumerator();
                    iterator.MoveNext(); )
            {
                DictionaryEntry mapEntry = (DictionaryEntry)iterator.Current;
                long entryId = (long)mapEntry.Key;

                if (Query(entryId, q))
                {
                    results.Add(entryId);
                }
            }

            return results;
        }

        public IList<long> Query(WorkflowExpressionQuery q)
        {
            List<long> results = new List<long>();

            for (IDictionaryEnumerator iterator = entryCache.GetEnumerator();
                    iterator.MoveNext(); )
            {
                DictionaryEntry mapEntry = (DictionaryEntry)iterator.Current;
                long entryId = (long)mapEntry.Key;

                if (Query(entryId, q))
                {
                    results.Add(entryId);
                }
            }

            return results;
        }

        private bool checkExpression(long entryId, FieldExpression expression)
        {
            object value = expression.Value;
            int operat = expression.Operator;
            int field = expression.Field;
            int context = expression.Context;

            long id = entryId;

            if (context == FieldExpression.ENTRY)
            {
                SimpleWorkflowEntry theEntry = (SimpleWorkflowEntry)entryCache[id];

                if (field == FieldExpression.NAME)
                {
                    return this.compareText(theEntry.WorkflowName, (string)value, operat);
                }

                if (field == FieldExpression.STATE)
                {
                    return this.compareLong(Convert.ToInt64(value), theEntry.State, operat);
                }

                throw new InvalidParameterException("unknown field");
            }

            IList steps;

            if (context == FieldExpression.CURRENT_STEPS)
            {
                steps = (IList)currentStepsCache[id];
            }
            else if (context == FieldExpression.HISTORY_STEPS)
            {
                steps = (IList)historyStepsCache[id];
            }
            else
            {
                throw new InvalidParameterException("unknown field context");
            }

            if (steps == null)
            {
                return false;
            }

            bool expressionResult = false;

            switch (field)
            {
                case FieldExpression.ACTION:

                    long actionId = Convert.ToInt64(value);

                    for (IEnumerator iterator = steps.GetEnumerator(); iterator.MoveNext(); )
                    {
                        SimpleStep step = (SimpleStep)iterator.Current;

                        if (this.compareLong(step.ActionId, actionId, operat))
                        {
                            expressionResult = true;

                            break;
                        }
                    }

                    break;

                case FieldExpression.CALLER:

                    string caller = (string)value;

                    for (IEnumerator iterator = steps.GetEnumerator(); iterator.MoveNext(); )
                    {
                        SimpleStep step = (SimpleStep)iterator.Current;

                        if (this.compareText(step.Caller, caller, operat))
                        {
                            expressionResult = true;

                            break;
                        }
                    }

                    break;

                case FieldExpression.FINISH_DATE:

                    DateTime? finishDate = (DateTime?)value;

                    for (IEnumerator iterator = steps.GetEnumerator(); iterator.MoveNext(); )
                    {
                        SimpleStep step = (SimpleStep)iterator.Current;

                        if (this.compareDate(step.FinishDate, finishDate, operat))
                        {
                            expressionResult = true;

                            break;
                        }
                    }

                    break;

                case FieldExpression.OWNER:

                    string owner = (string)value;

                    for (IEnumerator iterator = steps.GetEnumerator(); iterator.MoveNext(); )
                    {
                        SimpleStep step = (SimpleStep)iterator.Current;

                        if (this.compareText(step.Owner, owner, operat))
                        {
                            expressionResult = true;

                            break;
                        }
                    }

                    break;

                case FieldExpression.START_DATE:

                    DateTime startDate = (DateTime)value;

                    for (IEnumerator iterator = steps.GetEnumerator(); iterator.MoveNext(); )
                    {
                        SimpleStep step = (SimpleStep)iterator.Current;

                        if (this.compareDate(step.StartDate, startDate, operat))
                        {
                            expressionResult = true;

                            break;
                        }
                    }

                    break;

                case FieldExpression.STEP:

                    int stepId = Convert.ToInt32(value);

                    for (IEnumerator iterator = steps.GetEnumerator(); iterator.MoveNext(); )
                    {
                        SimpleStep step = (SimpleStep)iterator.Current;

                        if (this.compareLong(step.StepId, stepId, operat))
                        {
                            expressionResult = true;

                            break;
                        }
                    }

                    break;

                case FieldExpression.STATUS:

                    string status = (string)value;

                    for (IEnumerator iterator = steps.GetEnumerator(); iterator.MoveNext(); )
                    {
                        SimpleStep step = (SimpleStep)iterator.Current;

                        if (this.compareText(step.Status, status, operat))
                        {
                            expressionResult = true;

                            break;
                        }
                    }

                    break;

                case FieldExpression.DUE_DATE:

                    DateTime? dueDate = (DateTime?)value;

                    for (IEnumerator iterator = steps.GetEnumerator(); iterator.MoveNext(); )
                    {
                        SimpleStep step = (SimpleStep)iterator.Current;

                        if (this.compareDate(step.DueDate, dueDate, operat))
                        {
                            expressionResult = true;

                            break;
                        }
                    }

                    break;
            }

            if (expression.Negate)
            {
                return !expressionResult;
            }
            else
            {
                return expressionResult;
            }
        }

        private bool checkNestedExpression(long entryId, NestedExpression nestedExpression)
        {
            for (int i = 0; i < nestedExpression.ExpressionCount; i++)
            {
                bool expressionResult;
                Expression expression = nestedExpression.GetExpression(i);

                if (expression.IsNested())
                {
                    expressionResult = this.checkNestedExpression(entryId, (NestedExpression)expression);
                }
                else
                {
                    expressionResult = this.checkExpression(entryId, (FieldExpression)expression);
                }

                if (nestedExpression.ExpressionOperator == NestedExpression.AND)
                {
                    if (expressionResult == false)
                    {
                        return nestedExpression.Negate;
                    }
                }
                else if (nestedExpression.ExpressionOperator == NestedExpression.OR)
                {
                    if (expressionResult == true)
                    {
                        return !nestedExpression.Negate;
                    }
                }
            }

            if (nestedExpression.ExpressionOperator == NestedExpression.AND)
            {
                return !nestedExpression.Negate;
            }
            else if (nestedExpression.ExpressionOperator == NestedExpression.OR)
            {
                return nestedExpression.Negate;
            }

            throw new InvalidParameterException("unknown operator");
        }

        private bool compareDate(DateTime value1, DateTime value2, int operat)
        {
            switch (operat)
            {
                case FieldExpression.EQUALS:
                    return value1.CompareTo(value2) == 0;

                case FieldExpression.NOT_EQUALS:
                    return value1.CompareTo(value2) != 0;

                case FieldExpression.GT:
                    return (value1.CompareTo(value2) > 0);

                case FieldExpression.LT:
                    return value1.CompareTo(value2) < 0;
            }

            throw new InvalidParameterException("unknown field operator");
        }

        private bool compareDate(DateTime? value1, DateTime? value2, int operat)
        {
            switch (operat)
            {
                case FieldExpression.EQUALS:
                    return value1.Equals(value2);

                case FieldExpression.NOT_EQUALS:
                    return !value1.Equals(value2);

                case FieldExpression.GT:
                    if (value1.HasValue)
                    {
                        if (value2.HasValue)
                            return value1.Value.CompareTo(value2.Value) > 0;
                        else
                            return true;
                    }
                    else
                    {
                        return false;
                    }

                case FieldExpression.LT:
                    if (value1.HasValue)
                    {
                        if (value2.HasValue)
                            return value1.Value.CompareTo(value2.Value) < 0;
                        else
                            return false;
                    }
                    else
                    {
                        return true;
                    }

                    //return value1.CompareTo(value2) < 0;
            }

            throw new InvalidParameterException("unknown field operator");
        }

        private bool compareLong(long value1, long value2, int operat)
        {
            switch (operat)
            {
                case FieldExpression.EQUALS:
                    return value1 == value2;

                case FieldExpression.NOT_EQUALS:
                    return value1 != value2;

                case FieldExpression.GT:
                    return value1 > value2;

                case FieldExpression.LT:
                    return value1 < value2;
            }

            throw new InvalidParameterException("unknown field operator");
        }

        private bool compareText(string value1, string value2, int operat)
        {
            switch (operat)
            {
                case FieldExpression.EQUALS:
                    return value1 != null && value1.Equals(value2);

                case FieldExpression.NOT_EQUALS:
                    return !(value1 != null && value1.Equals(value2));

                case FieldExpression.GT:
                    return value1 != null && value1.CompareTo(value2) > 0;

                case FieldExpression.LT:
                    return value1 != null && value1.CompareTo(value2) < 0;
            }

            throw new InvalidParameterException("unknown field operator");
        }

        private bool Query(long entryId, WorkflowQuery q)
        {
            if (q.Left == null)
            {
                return QueryBasic(entryId, q);
            }
            else
            {
                switch (q.Operator)
                {
                    case WorkflowQuery.AND:
                        return Query(entryId, q.Left) && Query(entryId, q.Right);

                    case WorkflowQuery.OR:
                        return Query(entryId, q.Left) || Query(entryId, q.Right);

                    case WorkflowQuery.XOR:
                        return Query(entryId, q.Left) ^ Query(entryId, q.Right);
                }
            }

            return false;
        }

        private bool Query(long entryId, WorkflowExpressionQuery q)
        {
            Expression expression = q.Expression;

            if (expression.IsNested())
            {
                return this.checkNestedExpression(entryId, (NestedExpression)expression);
            }
            else
            {
                return this.checkExpression(entryId, (FieldExpression)expression);
            }
        }

        private bool QueryBasic(long entryId, WorkflowQuery query)
        {
            // the query object is a comparison
            object value = query.Value;
            int operat = query.Operator;
            int field = query.Field;
            int type = query.Type;

            switch (operat)
            {
                case WorkflowQuery.EQUALS:
                    return QueryEquals(entryId, field, type, value);

                case WorkflowQuery.NOT_EQUALS:
                    return queryNotEquals(entryId, field, type, value);

                case WorkflowQuery.GT:
                    return QueryGreaterThan(entryId, field, type, value);

                case WorkflowQuery.LT:
                    return queryLessThan(entryId, field, type, value);
            }

            return false;
        }

        private bool QueryEquals(long entryId, int field, int type, object value)
        {
            IList steps;

            if (type == WorkflowQuery.CURRENT)
            {
                steps = (IList)currentStepsCache[entryId];
            }
            else
            {
                steps = (IList)historyStepsCache[entryId];
            }

            if (steps == null)
            {
                return false;
            }

            switch (field)
            {
                case WorkflowQuery.ACTION:

                    long actionId = Convert.ToInt64(value);

                    for (IEnumerator iterator = steps.GetEnumerator(); iterator.MoveNext(); )
                    {
                        SimpleStep step = (SimpleStep)iterator.Current;

                        if (step.ActionId == actionId)
                        {
                            return true;
                        }
                    }

                    return false;

                case WorkflowQuery.CALLER:

                    string caller = (string)value;

                    for (IEnumerator iterator = steps.GetEnumerator(); iterator.MoveNext(); )
                    {
                        SimpleStep step = (SimpleStep)iterator.Current;

                        if (step.Caller != null && step.Caller.Equals(caller))
                        {
                            return true;
                        }
                    }

                    return false;

                case WorkflowQuery.FINISH_DATE:

                    DateTime? finishDate = (DateTime?)value;

                    for (IEnumerator iterator = steps.GetEnumerator(); iterator.MoveNext(); )
                    {
                        SimpleStep step = (SimpleStep)iterator.Current;

                        if (finishDate.Equals(step.FinishDate))
                        {
                            return true;
                        }
                    }

                    return false;

                case WorkflowQuery.OWNER:

                    string owner = (string)value;

                    for (IEnumerator iterator = steps.GetEnumerator(); iterator.MoveNext(); )
                    {
                        SimpleStep step = (SimpleStep)iterator.Current;

                        if (step.Owner != null && step.Owner.Equals(owner))
                        {
                            return true;
                        }
                    }

                    return false;

                case WorkflowQuery.START_DATE:

                    DateTime startDate = (DateTime)value;

                    for (IEnumerator iterator = steps.GetEnumerator(); iterator.MoveNext(); )
                    {
                        SimpleStep step = (SimpleStep)iterator.Current;

                        if (startDate.Equals(step.StartDate))
                        {
                            return true;
                        }
                    }

                    return false;

                case WorkflowQuery.STEP:

                    int stepId = Convert.ToInt32(value);

                    for (IEnumerator iterator = steps.GetEnumerator(); iterator.MoveNext(); )
                    {
                        SimpleStep step = (SimpleStep)iterator.Current;

                        if (stepId == step.StepId)
                        {
                            return true;
                        }
                    }

                    return false;

                case WorkflowQuery.STATUS:

                    string status = (string)value;

                    for (IEnumerator iterator = steps.GetEnumerator(); iterator.MoveNext(); )
                    {
                        SimpleStep step = (SimpleStep)iterator.Current;

                        if (step.Status != null && step.Status.Equals(status))
                        {
                            return true;
                        }
                    }

                    return false;
            }

            return false;
        }

        private bool QueryGreaterThan(long entryId, int field, int type, object value)
        {
            IList steps;

            if (type == WorkflowQuery.CURRENT)
            {
                steps = (IList)currentStepsCache[entryId];
            }
            else
            {
                steps = (IList)historyStepsCache[entryId];
            }

            switch (field)
            {
                case WorkflowQuery.ACTION:

                    long actionId = Convert.ToInt64(value);

                    for (IEnumerator iterator = steps.GetEnumerator(); iterator.MoveNext(); )
                    {
                        SimpleStep step = (SimpleStep)iterator.Current;

                        if (step.ActionId > actionId)
                        {
                            return true;
                        }
                    }

                    return false;

                case WorkflowQuery.CALLER:

                    string caller = (string)value;

                    for (IEnumerator iterator = steps.GetEnumerator(); iterator.MoveNext(); )
                    {
                        SimpleStep step = (SimpleStep)iterator.Current;

                        if (step.Caller != null && step.Caller.CompareTo(caller) > 0)
                        {
                            return true;
                        }
                    }

                    return false;

                case WorkflowQuery.FINISH_DATE:

                    DateTime? finishDate = (DateTime?)value;

                    for (IEnumerator iterator = steps.GetEnumerator(); iterator.MoveNext(); )
                    {
                        SimpleStep step = (SimpleStep)iterator.Current;

                        //if (step.FinishDate.CompareTo(finishDate) > 0)
                        //{
                        //    return true;
                        //}
                        DateTime? value1 = step.FinishDate;
                        DateTime? value2 = finishDate;
                        if (value1.HasValue)
                        {
                            if (value2.HasValue)
                                return value1.Value.CompareTo(value2.Value) > 0;
                            else
                                return true;
                        }
                        else
                        {
                            return false;
                        }
                    }

                    return false;

                case WorkflowQuery.OWNER:

                    string owner = (string)value;

                    for (IEnumerator iterator = steps.GetEnumerator(); iterator.MoveNext(); )
                    {
                        SimpleStep step = (SimpleStep)iterator.Current;

                        if (step.Owner != null && step.Owner.CompareTo(owner) > 0)
                        {
                            return true;
                        }
                    }

                    return false;

                case WorkflowQuery.START_DATE:

                    DateTime startDate = (DateTime)value;

                    for (IEnumerator iterator = steps.GetEnumerator(); iterator.MoveNext(); )
                    {
                        SimpleStep step = (SimpleStep)iterator.Current;

                        if (step.StartDate.CompareTo(startDate) > 0)
                        {
                            return true;
                        }
                    }

                    return false;

                case WorkflowQuery.STEP:

                    int stepId = Convert.ToInt32(value);

                    for (IEnumerator iterator = steps.GetEnumerator(); iterator.MoveNext(); )
                    {
                        SimpleStep step = (SimpleStep)iterator.Current;

                        if (step.StepId > stepId)
                        {
                            return true;
                        }
                    }

                    return false;

                case WorkflowQuery.STATUS:

                    string status = (string)value;

                    for (IEnumerator iterator = steps.GetEnumerator(); iterator.MoveNext(); )
                    {
                        SimpleStep step = (SimpleStep)iterator.Current;

                        if (ConvertUtil.GetSafeString(step.Status).CompareTo(status) > 0)
                        {
                            return true;
                        }
                    }

                    return false;
            }

            return false;
        }

        private bool queryLessThan(long entryId, int field, int type, object value)
        {
            IList steps;

            if (type == WorkflowQuery.CURRENT)
            {
                steps = (IList)currentStepsCache[entryId];
            }
            else
            {
                steps = (IList)historyStepsCache[entryId];
            }

            switch (field)
            {
                case WorkflowQuery.ACTION:

                    long actionId = Convert.ToInt64(value);

                    foreach  (SimpleStep step in steps)
                    {
                        if (step.ActionId < actionId)
                        {
                            return true;
                        }
                    }

                    return false;

                case WorkflowQuery.CALLER:

                    String caller = (String)value;

                    foreach (SimpleStep step in steps)
                    {
                        if (ConvertUtil.GetSafeString(step.Caller).CompareTo(caller) < 0)
                        {
                            return true;
                        }
                    }

                    return false;

                case WorkflowQuery.FINISH_DATE:

                    DateTime? finishDate = (DateTime?)value;

                    foreach (SimpleStep step in steps)
                    {
                        //if (step.FinishDate.CompareTo(finishDate) < 0)
                        //{
                        //    return true;
                        //}
                        DateTime? value1 = step.FinishDate;
                        DateTime? value2 = finishDate;
                        if (value1.HasValue)
                        {
                            if (value2.HasValue)
                                return value1.Value.CompareTo(value2.Value) < 0;
                            else
                                return false;
                        }
                        else
                        {
                            return true;
                        }
                    }

                    return false;

                case WorkflowQuery.OWNER:

                    string owner = (string)value;

                    foreach (SimpleStep step in steps)
                    {
                        if (ConvertUtil.GetSafeString(step.Owner).CompareTo(owner) < 0)
                        {
                            return true;
                        }
                    }

                    return false;

                case WorkflowQuery.START_DATE:

                    DateTime startDate = (DateTime)value;

                    foreach (SimpleStep step in steps)
                    {
                        if (step.StartDate.CompareTo(startDate) < 0)
                        {
                            return true;
                        }
                    }

                    return false;

                case WorkflowQuery.STEP:

                    int stepId = Convert.ToInt32(value);

                    for (IEnumerator iterator = steps.GetEnumerator(); iterator.MoveNext(); )
                    {
                        SimpleStep step = (SimpleStep)iterator.Current;

                        if (step.StepId < stepId)
                        {
                            return true;
                        }
                    }

                    return false;

                case WorkflowQuery.STATUS:

                    string status = (string)value;

                    for (IEnumerator iterator = steps.GetEnumerator(); iterator.MoveNext(); )
                    {
                        SimpleStep step = (SimpleStep)iterator.Current;

                        if (ConvertUtil.GetSafeString(step.Status).CompareTo(status) < 0)
                        {
                            return true;
                        }
                    }

                    return false;
            }

            return false;
        }

        private bool queryNotEquals(long entryId, int field, int type, object value)
        {
            IList steps;

            if (type == WorkflowQuery.CURRENT)
            {
                steps = (IList)currentStepsCache[entryId];
            }
            else
            {
                steps = (IList)historyStepsCache[entryId];
            }

            switch (field)
            {
                case WorkflowQuery.ACTION:

                    long actionId = Convert.ToInt64(value);

                    for (IEnumerator iterator = steps.GetEnumerator(); iterator.MoveNext(); )
                    {
                        SimpleStep step = (SimpleStep)iterator.Current;

                        if (step.ActionId != actionId)
                        {
                            return true;
                        }
                    }

                    return false;

                case WorkflowQuery.CALLER:

                    string caller = (string)value;

                    for (IEnumerator iterator = steps.GetEnumerator(); iterator.MoveNext(); )
                    {
                        SimpleStep step = (SimpleStep)iterator.Current;

                        if (!ConvertUtil.GetSafeString(step.Caller).Equals(caller))
                        {
                            return true;
                        }
                    }

                    return false;

                case WorkflowQuery.FINISH_DATE:

                    DateTime? finishDate = (DateTime?)value;

                    for (IEnumerator iterator = steps.GetEnumerator(); iterator.MoveNext(); )
                    {
                        SimpleStep step = (SimpleStep)iterator.Current;

                        if (!finishDate.Equals(step.FinishDate))
                        {
                            return true;
                        }
                    }

                    return false;

                case WorkflowQuery.OWNER:

                    string owner = (string)value;

                    for (IEnumerator iterator = steps.GetEnumerator(); iterator.MoveNext(); )
                    {
                        SimpleStep step = (SimpleStep)iterator.Current;

                        if (!ConvertUtil.GetSafeString(step.Owner).Equals(owner))
                        {
                            return true;
                        }
                    }

                    return false;

                case WorkflowQuery.START_DATE:

                    DateTime startDate = (DateTime)value;

                    for (IEnumerator iterator = steps.GetEnumerator(); iterator.MoveNext(); )
                    {
                        SimpleStep step = (SimpleStep)iterator.Current;

                        if (!startDate.Equals(step.StartDate))
                        {
                            return true;
                        }
                    }

                    return false;

                case WorkflowQuery.STEP:

                    int stepId = Convert.ToInt32(value);

                    for (IEnumerator iterator = steps.GetEnumerator(); iterator.MoveNext(); )
                    {
                        SimpleStep step = (SimpleStep)iterator.Current;

                        if (stepId != step.StepId)
                        {
                            return true;
                        }
                    }

                    return false;

                case WorkflowQuery.STATUS:

                    string status = (string)value;

                    for (IEnumerator iterator = steps.GetEnumerator(); iterator.MoveNext(); )
                    {
                        SimpleStep step = (SimpleStep)iterator.Current;

                        if (!ConvertUtil.GetSafeString(step.Status).Equals(status))
                        {
                            return true;
                        }
                    }

                    return false;
            }

            return false;
        }

        public int BeginTransaction()
        {
            return 0;
        }

        public void RollbackTransaction()
        {
            // do nothing.
        }

        public void CommitTransaction()
        {
            // do nothing.
        }
    }
}